home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / access / common / heaptuple.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  31.3 KB  |  1,338 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    heaptuple.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    This file contains heap tuple accessor and mutator
  7.  *    routines, as well as a few various tuple utilities.
  8.  *
  9.  *   INTERFACE ROUTINES
  10.  *    heap_attisnull        
  11.  *    heap_sysattrlen
  12.  *    heap_sysattrbyval
  13.  *    heap_getsysattr
  14.  *    heap_getattr
  15.  *    heap_addheader        
  16.  *    heap_copytuple
  17.  *    heap_formtuple 
  18.  *    heap_modifytuple
  19.  *    
  20.  *   NOTES
  21.  *    The old interface functions have been converted to macros
  22.  *    and moved to heapam.h
  23.  *    
  24.  *   IDENTIFICATION
  25.  *    $Header: /private/postgres/src/access/common/RCS/heaptuple.c,v 1.33 1992/07/09 03:51:56 hong Exp $
  26.  * ----------------------------------------------------------------
  27.  */
  28. #include "tmp/c.h"
  29.  
  30. #include "access/htup.h"
  31. #include "access/itup.h"
  32. #include "access/tupmacs.h"
  33. #include "access/skey.h"
  34. #include "rules/rac.h"
  35. #include "storage/buf.h"
  36. #include "storage/bufpage.h"        /* for MAXTUPLEN */
  37. #include "storage/itempos.h"
  38. #include "storage/itemptr.h"
  39. #include "storage/page.h"
  40. #include "storage/form.h"
  41. #include "utils/memutils.h"
  42. #include "utils/log.h"
  43. #include "utils/palloc.h"
  44. #include "utils/rel.h"
  45. #include "utils/nabstime.h"
  46. #include "rules/prs2.h"
  47.  
  48. /* this is so the sparcstation debugger works */
  49.  
  50. #ifndef NO_ASSERT_CHECKING
  51. #ifdef sparc
  52. #define register
  53. #endif /* sparc */
  54. #endif /* NO_ASSERT_CHECKING */
  55.  
  56. RcsId("$Header: /private/postgres/src/access/common/RCS/heaptuple.c,v 1.33 1992/07/09 03:51:56 hong Exp $");
  57.  
  58. void
  59. set_use_cacheoffgetattr(x)
  60.     int x;
  61. {}
  62.  
  63. /* ----------------------------------------------------------------
  64.  *            misc support routines
  65.  * ----------------------------------------------------------------
  66.  */
  67.  
  68. /* ----------------
  69.  *    ComputeDataSize
  70.  * ----------------
  71.  */
  72. Size
  73. ComputeDataSize(numberOfAttributes, att, value, nulls)
  74.     AttributeNumber    numberOfAttributes;
  75.     Attribute           att[];
  76.     Datum        value[];
  77.     char        nulls[];
  78. {
  79.     register uint32    length;
  80.     register int    i;
  81.  
  82.     for (length = 0, i = 0; i < numberOfAttributes; i++)
  83.     {
  84.     if (nulls[i] != ' ') continue;
  85.  
  86.     switch (att[i]->attlen) 
  87.     {
  88.         case -1:
  89.         /*
  90.          * This is the size of the disk representation and so
  91.          * must inclue the additional sizeof long.
  92.          */
  93.         length = LONGALIGN(length)
  94.                + VARSIZE(DatumGetPointer(value[i]));
  95.         break;
  96.         case sizeof(char):
  97.         length++;
  98.         break;
  99.         case sizeof(short):
  100.         length = SHORTALIGN(length + sizeof(short));
  101.         break;
  102.         default:
  103.         length = LONGALIGN(length) + att[i]->attlen;
  104.         break;
  105.     }
  106.     }
  107.  
  108.     return length;
  109. }
  110.  
  111. /* ----------------
  112.  *    DataFill
  113.  * ----------------
  114.  */
  115.  
  116. void
  117. DataFill(data, numberOfAttributes, att, value, nulls, infomask, bit)
  118.     Pointer data;
  119.     AttributeNumber    numberOfAttributes;
  120.     Attribute        att[];
  121.     Datum        value[];
  122.     char        nulls[];
  123.     char        *infomask;
  124.     bits8        bit[];
  125. {
  126.     bits8    *bitP;
  127.     int        bitmask;
  128.     uint32    length;
  129.     int        i;
  130.  
  131.     if (bit != NULL)
  132.     {
  133.         bitP = &bit[-1];
  134.         bitmask = CSIGNBIT;
  135.     }
  136.  
  137.     *infomask = 0;
  138.  
  139.     for (i = 0; i < numberOfAttributes; i++)
  140.     {
  141.     if (bit != NULL)
  142.     {
  143.         if (bitmask != CSIGNBIT) {
  144.             bitmask <<= 1;
  145.         } else {
  146.             bitP += 1;
  147.             *bitP = 0x0;
  148.             bitmask = 1;
  149.         }
  150.  
  151.         if (nulls[i] == 'n') 
  152.         {
  153.             *infomask |= 0x1;
  154.             continue;
  155.         }
  156.  
  157.         *bitP |= bitmask;
  158.     }
  159.  
  160.     switch (att[i]->attlen)
  161.     {
  162.         case -1:
  163.             *infomask |= 0x2;
  164.             data = (Pointer) LONGALIGN((char *) data);
  165.             length = VARSIZE(DatumGetPointer(value[i]));
  166.             bcopy(DatumGetPointer(value[i]), data, length);
  167.             data += length;
  168.         break;
  169.         case sizeof(char):
  170.         * (char *) data = (att[i]->attbyval ?
  171.                    DatumGetChar(value[i]) :
  172.                    * (char *) value[i]);
  173.         data += sizeof(char);
  174.         break;
  175.         case sizeof(short):
  176.         data = (Pointer) SHORTALIGN(data);
  177.         * (short *) data = (att[i]->attbyval ?
  178.                             DatumGetInt16(value[i]) :
  179.                     * (short *) value[i]);
  180.         data += sizeof(short);
  181.         break;
  182.         case 3: /* XXX */
  183.         case sizeof(long):
  184.         data = (Pointer) LONGALIGN(data);
  185.         * (long *) data = (att[i]->attbyval ?
  186.                    DatumGetInt32(value[i]) :
  187.                    * (long *) value[i]);
  188.         data += sizeof(long);
  189.         break;
  190.         default:
  191.         data = (Pointer) LONGALIGN(data);
  192.         bcopy(DatumGetPointer(value[i]), data, att[i]->attlen);
  193.         data += att[i]->attlen;
  194.         break;
  195.  
  196.     }
  197.     }
  198. }
  199.  
  200. /* ----------------------------------------------------------------
  201.  *            heap tuple interface
  202.  * ----------------------------------------------------------------
  203.  */
  204.  
  205. /* ----------------
  206.  *    heap_attisnull    - returns 1 iff tuple attribute is not present
  207.  * ----------------
  208.  */
  209. int
  210. heap_attisnull(tup, attnum)
  211.     HeapTuple    tup;
  212.     int        attnum;
  213. {
  214.     register char    *bp;    
  215.     register int    byte;
  216.     register int    finalbit;
  217.  
  218.     if (attnum > (int)tup->t_natts)
  219.     return (1);
  220.  
  221.     if (HeapTupleNoNulls(tup)) return(0);
  222.  
  223.     if (attnum > 0) {
  224.     return(att_isnull(attnum - 1, tup->t_bits));
  225.     } else
  226.     switch (attnum) {
  227.     case SelfItemPointerAttributeNumber:
  228.     case RuleLockAttributeNumber:
  229.     case ObjectIdAttributeNumber:
  230.     case MinTransactionIdAttributeNumber:
  231.     case MinCommandIdAttributeNumber:
  232.     case MaxTransactionIdAttributeNumber:
  233.     case MaxCommandIdAttributeNumber:
  234.     case ChainItemPointerAttributeNumber:
  235.     case AnchorItemPointerAttributeNumber:
  236.     case MinAbsoluteTimeAttributeNumber:
  237.     case MaxAbsoluteTimeAttributeNumber:
  238.     case VersionTypeAttributeNumber:
  239.         break;
  240.  
  241.     case 0:
  242.         elog(WARN, "heap_attisnull: zero attnum disallowed");
  243.  
  244.     default:
  245.         elog(WARN, "heap_attisnull: undefined negative attnum");
  246.     }
  247.  
  248.     return (0);
  249. }
  250.  
  251. /* ----------------------------------------------------------------
  252.  *         system attribute heap tuple support
  253.  * ----------------------------------------------------------------
  254.  */
  255.  
  256. /* ----------------
  257.  *    heap_sysattrlen
  258.  *
  259.  *    This routine returns the length of a system attribute.
  260.  * ----------------
  261.  */
  262. int
  263. heap_sysattrlen(attno)
  264.     AttributeNumber    attno;
  265. {
  266.     HeapTupleData    f;
  267.     int            len;
  268.     switch (attno) {
  269.     case SelfItemPointerAttributeNumber:
  270.         len = sizeof (f.t_ctid);
  271.         break;
  272.     case RuleLockAttributeNumber:
  273.         len = sizeof f.t_lock;
  274.         break;
  275.     case ObjectIdAttributeNumber:
  276.         len = sizeof f.t_oid;
  277.         break;
  278.     case MinTransactionIdAttributeNumber:
  279.         len = sizeof f.t_xmin;
  280.         break;
  281.     case MinCommandIdAttributeNumber:
  282.         len = sizeof f.t_cmin;
  283.         break;
  284.     case MaxTransactionIdAttributeNumber:
  285.         len = sizeof f.t_xmax;
  286.         break;
  287.     case MaxCommandIdAttributeNumber:
  288.         len = sizeof f.t_cmax;
  289.         break;
  290.     case ChainItemPointerAttributeNumber:
  291.         len = sizeof (f.t_chain);
  292.         break;
  293.     case AnchorItemPointerAttributeNumber:
  294.         elog(WARN, "heap_sysattrlen: field t_anchor does not exist!");
  295.         break;
  296.     case MinAbsoluteTimeAttributeNumber:
  297.         len = sizeof f.t_tmin;
  298.         break;
  299.     case MaxAbsoluteTimeAttributeNumber:
  300.         len = sizeof f.t_tmax;
  301.         break;
  302.     case VersionTypeAttributeNumber:
  303.         len = sizeof f.t_vtype;
  304.         break;
  305.     default:
  306.         elog(WARN, "sysattrlen: System attribute number %d unknown.",
  307.          attno);
  308.         len = 0;
  309.         break;
  310.     }
  311.     return (len);
  312. }
  313.  
  314. /* ----------------
  315.  *    heap_sysattrbyval
  316.  *
  317.  *    This routine returns the "by-value" property of a system attribute.
  318.  * ----------------
  319.  */
  320. bool
  321. heap_sysattrbyval(attno)
  322.     AttributeNumber    attno;
  323. {
  324.     HeapTupleData    f;
  325.     bool        byval;
  326.     
  327.     switch (attno) {
  328.     case SelfItemPointerAttributeNumber:
  329.         byval = false;
  330.         break;
  331.     case RuleLockAttributeNumber:
  332.         byval = false;
  333.         break;
  334.     case ObjectIdAttributeNumber:
  335.         byval = true;
  336.         break;
  337.     case MinTransactionIdAttributeNumber:
  338.         byval = true;
  339.         break;
  340.     case MinCommandIdAttributeNumber:
  341.         byval = true;
  342.         break;
  343.     case MaxTransactionIdAttributeNumber:
  344.         byval = true;
  345.         break;
  346.     case MaxCommandIdAttributeNumber:
  347.         byval = true;
  348.         break;
  349.     case ChainItemPointerAttributeNumber:
  350.         byval = false;
  351.         break;
  352.     case AnchorItemPointerAttributeNumber:
  353.         byval = false;
  354.         break;
  355.     case MinAbsoluteTimeAttributeNumber:
  356.         byval = true;
  357.         break;
  358.     case MaxAbsoluteTimeAttributeNumber:
  359.         byval = true;
  360.         break;
  361.     case VersionTypeAttributeNumber:
  362.         byval = true;
  363.         break;
  364.     default:
  365.         byval = true;
  366.         elog(WARN, "sysattrbyval: System attribute number %d unknown.",
  367.          attno);
  368.         break;
  369.     }
  370.     
  371.     return byval;
  372. }
  373.  
  374. /* ----------------
  375.  *    heap_getsysattr
  376.  * ----------------
  377.  */
  378. char *
  379. heap_getsysattr(tup, b, attnum)
  380.     HeapTuple    tup;
  381.     Buffer    b;
  382.     int        attnum;
  383. {
  384.     RuleLock    lock;
  385.         
  386.     switch (attnum) {
  387.     case SelfItemPointerAttributeNumber:
  388.     return ((char *)&tup->t_ctid);
  389.  
  390.     case RuleLockAttributeNumber:
  391.     /*---------------
  392.      * A rule lock is ALWAYS non-null.
  393.      * 'HeapTupleGetRuleLock' will always return a valid
  394.      * rule lock.
  395.      * So the following 3 lines of code are obsolete &
  396.      * commented out.
  397.      *
  398.      * >>if (PointerIsValid(isnull) && !RuleLockIsValid(lock)) {
  399.      * >>  *isnull = (bool)1;
  400.      * >>}
  401.      *
  402.      * BTW, the reason for all that is that "ExecEvalExpr"
  403.      * refuses to evaluate an expression containing an
  404.      * InvalidRuleLock (if the 'isNull' atrgument is true)
  405.      * and returns a null Const node.
  406.      *---------------
  407.      */
  408.     lock = HeapTupleGetRuleLock(tup, b);
  409.     return ((char *)lock);
  410.     
  411.     case ObjectIdAttributeNumber:
  412.     return ((char *)tup->t_oid);
  413.     case MinTransactionIdAttributeNumber:
  414.     return ((char *)tup->t_xmin);
  415.     case MinCommandIdAttributeNumber:
  416.     return ((char *)tup->t_cmin);
  417.     case MaxTransactionIdAttributeNumber:
  418.     return ((char *)tup->t_xmax);
  419.     case MaxCommandIdAttributeNumber:
  420.     return ((char *)tup->t_cmax);
  421.     case ChainItemPointerAttributeNumber:
  422.     return ((char *)&tup->t_chain);
  423.     case AnchorItemPointerAttributeNumber:
  424.     elog(WARN, "heap_getsysattr: t_anchor does not exist!");
  425.     break;
  426.  
  427.     /*
  428.      *  For tmin and tmax, we need to do some extra work.  These don't
  429.      *  get filled in until the vacuum cleaner runs (or we manage to flush
  430.      *  a page after setting the value correctly below).  If the vacuum
  431.      *  cleaner hasn't run yet, then the times stored in the tuple are
  432.      *  wrong, and we need to look up the commit time of the transaction.
  433.      *  We cache this value in the tuple to avoid doing the work more than
  434.      *  once.
  435.      */
  436.  
  437.     case MinAbsoluteTimeAttributeNumber:
  438.     if (!AbsoluteTimeIsValid(tup->t_tmin) && 
  439.         TransactionIdDidCommit(tup->t_xmin))
  440.         tup->t_tmin = TransactionIdGetCommitTime(tup->t_xmin);
  441.     return ((char *)tup->t_tmin);
  442.     case MaxAbsoluteTimeAttributeNumber:
  443.     if (!AbsoluteTimeIsReal(tup->t_tmax))
  444.     {
  445.         if (TransactionIdDidCommit(tup->t_xmax))
  446.         tup->t_tmax = TransactionIdGetCommitTime(tup->t_xmax);
  447.         else
  448.         tup->t_tmax = EPOCH_ABSTIME;
  449.     }
  450.     return ((char *)tup->t_tmax);
  451.     case VersionTypeAttributeNumber:
  452.     return ((char *)tup->t_vtype);
  453.     default:
  454.     elog(WARN, "heap_getsysattr: undefined attnum %d", attnum);
  455.     }
  456.     return(NULL);
  457. }
  458.  
  459. /* ----------------
  460.  *    fastgetattr
  461.  *
  462.  *    This is a newer version of fastgetattr which attempts to be
  463.  *    faster by caching attribute offsets in the attribute descriptor.
  464.  *
  465.  *    an alternate way to speed things up would be to cache offsets
  466.  *    with the tuple, but that seems more difficult unless you take
  467.  *    the storage hit of actually putting those offsets into the
  468.  *    tuple you send to disk.  Yuck.
  469.  *
  470.  *    This scheme will be slightly slower than that, but should
  471.  *    preform well for queries which hit large #'s of tuples.  After
  472.  *    you cache the offsets once, examining all the other tuples using
  473.  *    the same attribute descriptor will go much quicker. -cim 5/4/91
  474.  * ----------------
  475.  */
  476.  
  477. char *
  478. fastgetattr(tup, attnum, att, isnull)
  479.     HeapTuple    tup;
  480.     unsigned    attnum;
  481.     struct    attribute *att[];
  482.     bool    *isnull;
  483. {
  484.     register char        *tp;        /* ptr to att in tuple */
  485.     register char        *bp;        /* ptr to att in tuple */
  486.     int             slow;        /* do we have to walk nulls? */
  487.  
  488.     /* ----------------
  489.      *    sanity checks
  490.      * ----------------
  491.      */
  492.  
  493.     Assert(PointerIsValid(isnull));
  494.     Assert(attnum > 0);
  495.  
  496.     /* ----------------
  497.      *   Three cases:
  498.      * 
  499.      *   1: No nulls and no variable length attributes.
  500.      *   2: Has a null or a varlena AFTER att.
  501.      *   3: Has nulls or varlenas BEFORE att.
  502.      * ----------------
  503.      */
  504.  
  505.     *isnull =  false;
  506.  
  507.     if (HeapTupleNoNulls(tup))
  508.     {
  509.     /* first attribute is always at position zero */
  510.  
  511.     attnum--;
  512.     if (att[attnum]->attcacheoff > 0)
  513.     {
  514.         return((char *) fetchatt(att + attnum, (Pointer) tup
  515.                 + tup->t_hoff + att[attnum]->attcacheoff));
  516.     }
  517.     else if (attnum == 0)
  518.     {
  519.          return((char *) fetchatt(att, (Pointer) tup + tup->t_hoff));
  520.     }
  521.  
  522.     tp = (Pointer) tup + tup->t_hoff;
  523.  
  524.     slow = 0;
  525.     }
  526.     else /* there's a null somewhere in the tuple */
  527.     {
  528.     bp = tup->t_bits;
  529.     tp = (Pointer) tup + tup->t_hoff;
  530.     slow = 0;
  531.     attnum--;
  532.  
  533.         /* ----------------
  534.          *    check to see if desired att is null
  535.          * ----------------
  536.          */
  537.  
  538.     if (att_isnull(attnum, bp)) 
  539.     {
  540.         *isnull = true;
  541.         return NULL;
  542.     }
  543.         /* ----------------
  544.      *      Now check to see if any preceeding bits are null...
  545.          * ----------------
  546.      */
  547.  
  548.     {
  549.         register int  i = 0; /* current offset in bp */
  550.  
  551.         for (i = 0; i < attnum && !slow; i++)
  552.         {
  553.         if (att_isnull(i, bp)) slow = 1;
  554.         }
  555.         }
  556.     }
  557.  
  558.     /* now check for any non-fixed length attrs before our attribute */
  559.  
  560.     if (!slow)
  561.     {
  562.     if (att[attnum]->attcacheoff > 0)
  563.     {
  564.         return((char *) fetchatt(att + attnum, tp + att[attnum]->attcacheoff));
  565.     }
  566.     else if (attnum == 0)
  567.     {
  568.          return((char *) fetchatt(att, (Pointer) tup + tup->t_hoff));
  569.     }
  570.     else if (!HeapTupleAllFixed(tup))
  571.     {
  572.         register int j = 0;
  573.  
  574.         for (j = 0; j < attnum && !slow; j++)
  575.         if (att[j]->attlen < 1) slow = 1;
  576.     }
  577.     }
  578.  
  579.     /*
  580.      * if slow is zero, and we got here, we know that we have a tuple with
  581.      * no nulls.  We also have to initialize the remainder of
  582.      * the attribute cached offset values.
  583.      */
  584.  
  585.     if (!slow)
  586.     {
  587.     register int j = 1;
  588.     register long off;
  589.  
  590.     /*
  591.      * need to set cache for some atts
  592.      */
  593.  
  594.     att[0]->attcacheoff = 0;
  595.  
  596.     while (att[j]->attcacheoff > 0) j++;
  597.  
  598.     off = att[j-1]->attcacheoff + att[j-1]->attlen;
  599.  
  600.     for (; j < attnum + 1; j++)
  601.     {
  602.         /*
  603.          * Fix me when going to a machine with more than a four-byte
  604.          * word!
  605.          */
  606.  
  607.         switch(att[j]->attlen)
  608.         {
  609.         case sizeof(char) : break;
  610.         case sizeof(short): off = SHORTALIGN(off); break;
  611.         default           : off = LONGALIGN(off); break;
  612.         }
  613.  
  614.         att[j]->attcacheoff = off;
  615.         off += att[j]->attlen;
  616.     }
  617.  
  618.     return((char *) fetchatt(att + attnum, tp + att[attnum]->attcacheoff));
  619.     }
  620.     else
  621.     {
  622.     register bool usecache = true;
  623.     register int off = 0;
  624.     register int savelen;
  625.     register int i;
  626.  
  627.     /*
  628.      * Now we know that we have to walk the tuple CAREFULLY.
  629.      *
  630.      * Note - This loop is a little tricky.  On iteration i we
  631.      * first set the offset for attribute i and figure out how much
  632.      * the offset should be incremented.  Finally, we need to align the
  633.      * offset based on the size of attribute i+1 (for which the offset
  634.      * has been computed). -mer 12 Dec 1991
  635.      */
  636.     
  637.     for (i = 0; i < attnum; i++)
  638.     {
  639.         if (!HeapTupleNoNulls(tup))
  640.         {
  641.         if (att_isnull(i, bp))
  642.         {
  643.             usecache = false;
  644.             continue;
  645.         }
  646.         }
  647.         switch (att[i]->attlen)
  648.         {
  649.         case sizeof(char)  : break;
  650.         case sizeof(short) : off = SHORTALIGN(off); break;
  651.         default            : off = LONGALIGN(off); break;
  652.         }
  653.         if (usecache && att[i]->attcacheoff > 0)
  654.         {
  655.         off = att[i]->attcacheoff;
  656.         if (att[i]->attlen == -1)
  657.         {
  658.             usecache = false;
  659.         }
  660.         }
  661.         else
  662.         {
  663.             if (usecache) att[i]->attcacheoff = off;
  664.         }
  665.  
  666.         switch(att[i]->attlen)
  667.         {
  668.         long *debugl;
  669.         char *debugc;
  670.  
  671.             case sizeof(char):
  672.                 off++;
  673.                 break;
  674.             case sizeof(short):
  675.                 off = off + sizeof(short);
  676.                 break;
  677.             case -1:
  678.                 usecache = false;
  679.             off += VARSIZE(tp + off);
  680.             break;
  681.         default:
  682.             off = off + att[i]->attlen;
  683.             break;
  684.         }
  685.     }
  686.     switch (att[attnum]->attlen)
  687.     {
  688.         case sizeof(char)  : break;
  689.         case sizeof(short) : off = SHORTALIGN(off); break;
  690.         default            : off = LONGALIGN(off); break;
  691.     }
  692.     return((char *) fetchatt(att + attnum, tp + off));
  693.     }
  694. }
  695.  
  696. /* ----------------
  697.  *    heap_getattr
  698.  *
  699.  *    returns an attribute from a heap tuple.  uses 
  700.  * ----------------
  701.  */
  702. char *
  703. heap_getattr(tup, b, attnum, att, isnull)
  704.     HeapTuple    tup;
  705.     Buffer    b;
  706.     int        attnum;
  707.     struct    attribute *att[];
  708.     bool    *isnull;
  709. {
  710.     bool    localIsNull;
  711.  
  712.     /* ----------------
  713.      *    sanity checks
  714.      * ----------------
  715.      */
  716.     Assert(tup != NULL);
  717.  
  718.     if (! PointerIsValid(isnull))
  719.     isnull = &localIsNull;
  720.     
  721.     if (attnum > (int) tup->t_natts) {
  722.     *isnull = true;
  723.     return ((char *) NULL);
  724.     }
  725.  
  726.     /* ----------------
  727.      *    take care of user defined attributes
  728.      * ----------------
  729.      */
  730.     if (attnum > 0) {
  731.     char  *datum;
  732.     datum = fastgetattr(tup, attnum, att, isnull);
  733.     
  734.     return (datum);
  735.     }
  736.  
  737.     /* ----------------
  738.      *    take care of system attributes
  739.      * ----------------
  740.      */
  741.     *isnull = false;
  742.     return
  743.     heap_getsysattr(tup, b, attnum);
  744. }
  745.  
  746. /* ----------------
  747.  *    heap_copysimple
  748.  *
  749.  *    returns a copy of an entire tuple - w/o the multiple apge
  750.  *      wierdness of heap_copytuple
  751.  * ----------------
  752.  */
  753. HeapTuple
  754. heap_copysimple(tuple)
  755.     HeapTuple    tuple;
  756. {
  757.     HeapTuple   newtup;
  758.  
  759.     Assert (HeapTupleIsValid(tuple));
  760.  
  761.     newtup = (HeapTuple)palloc(tuple->t_len);
  762.     bcopy(tuple, newtup, tuple->t_len);
  763.  
  764.     /*
  765.      * Don't convert the rule lock to its memory representation,
  766.      * just copy the tid.  If we actually have a memory rule lock
  767.      * then we have to copy it to 'palloc'ed space via the prs2locks
  768.      * utilities.
  769.      *
  770.      * old comments:
  771.      *
  772.      * AAAAAAAAAAAAAAaaaaaaaaaaaaaaaaaaaaaaaaaaaaahhhhhhhhhhhhhhhhhhh!
  773.      * We have to copy to copy the RuleLock pointer too if it is in
  774.      * memory!!!!!!!!! May the Gods forgive me for the hack that is about
  775.      * to follow...  -mer 21:10:00 7 July 1992
  776.      */
  777.     if (tuple->t_locktype == MEM_RULE_LOCK)
  778.     {
  779.     if (RuleLockIsValid(tuple->t_lock.l_lock))
  780.         newtup->t_lock.l_lock = prs2CopyLocks(tuple->t_lock.l_lock);
  781.     else
  782.         newtup->t_lock.l_lock = InvalidRuleLock;
  783.     }
  784.     return newtup;
  785. }
  786. /* ----------------
  787.  *    heap_copytuple
  788.  *
  789.  *    returns a copy of an entire tuple
  790.  * ----------------
  791.  */
  792.  
  793. HeapTuple
  794. heap_copytuple(tuple, buffer, relation)
  795.     HeapTuple    tuple;
  796.     Buffer    buffer;
  797.     Relation    relation;
  798. {
  799.     RuleLock    ruleLock;
  800.     HeapTuple    newTuple = NULL;
  801.     
  802.     /* ----------------
  803.      *    sanity checks
  804.      * ----------------
  805.      */
  806.     Assert(BufferIsValid(buffer) || RelationIsValid(relation));
  807.     
  808.     if (! HeapTupleIsValid(tuple))
  809.     return (NULL);
  810.     
  811. #ifndef    BUGFREEEXECUTOR
  812.     /* XXX For now, just prevent an undetectable executor related error */
  813.     if (tuple->t_len > MAXTUPLEN) {
  814.     elog(WARN, "palloctup: cannot handle length %d tuples",
  815.          tuple->t_len);
  816.     }
  817. #endif BUGFREEEXECUTOR
  818.  
  819.     /* ----------------
  820.      *  fetch rule locks from the source tuple
  821.      *
  822.      * If the rule lock of the tuple passed to this routine
  823.      * is a pointer to a "disk memory representation" of a rule
  824.      * lock, convert it to the main memory representation (routine
  825.      * HeapTupleGetRuleLock does that).
  826.      * NOTE: HeapTupleGetRuleLock returns a COPY of the lock
  827.      * (which is exactly what we want...)
  828.      * ----------------
  829.      */
  830.     ruleLock = HeapTupleGetRuleLock(tuple, buffer);
  831.  
  832.     /* ----------------
  833.      *    allocate a new tuple
  834.      * ----------------
  835.      */
  836.     newTuple = (HeapTuple) palloc(tuple->t_len);
  837.     
  838.     /* ----------------
  839.      *    copy the tuple
  840.      * ----------------
  841.      */
  842.     if ((! BufferIsValid(buffer)) || tuple->t_len < MAXTUPLEN) {
  843.     /* ----------------
  844.      *  if tuple is not on disk, or it's small enough, then we
  845.      *  can just do a bcopy.
  846.      * ----------------
  847.      */
  848.     bcopy((char *)tuple, (char *)newTuple, (int)tuple->t_len);
  849.     } else {
  850.     /* ----------------
  851.      *  otherwise we have a disk tuple that spans several pages.
  852.      * ----------------
  853.      */
  854.     ItemSubposition    opos;
  855.     ItemSubposition    startpskip();
  856.     int        pfill();
  857.     extern        endpskip();
  858.     
  859.     opos = startpskip(buffer, relation, &tuple->t_ctid);
  860.     pfill(opos, (Pointer)newTuple);
  861.     endpskip();
  862.     }
  863.  
  864.     /* ----------------
  865.      *    fill in the rule lock information
  866.      * ----------------
  867.      */
  868.     newTuple->t_lock.l_lock = ruleLock;
  869.     newTuple->t_locktype = MEM_RULE_LOCK;
  870.     
  871.     /* ----------------
  872.      *    return the new copy
  873.      * ----------------
  874.      */
  875.     return
  876.     newTuple;
  877. }
  878.  
  879. /* ----------------
  880.  *    heap_deformtuple
  881.  *
  882.  *    the inverse of heap_formtuple (see below)
  883.  * ----------------
  884.  */
  885. void
  886. heap_deformtuple(tuple, tdesc, values, nulls)
  887.     HeapTuple       tuple;
  888.     TupleDescriptor tdesc;
  889.     Datum           values[];
  890.     char            nulls[];
  891. {
  892.     int i;
  893.     int natts;
  894.  
  895.     Assert(HeapTupleIsValid(tuple));
  896.  
  897.     natts = tuple->t_natts;
  898.     for (i = 0; i<natts; i++)
  899.     {
  900.     bool isnull;
  901.  
  902.     values[i] = (Datum)heap_getattr(tuple,
  903.                  InvalidBuffer,
  904.                  i+1,
  905.                  tdesc,
  906.                  &isnull);
  907.     if (isnull)
  908.         nulls[i] = 'n';
  909.     else
  910.         nulls[i] = ' ';
  911.     }
  912. }
  913.  
  914. /* ----------------
  915.  *    heap_formtuple 
  916.  *
  917.  *    constructs a tuple from the given value[] and null[] arrays
  918.  *
  919.  * old comments
  920.  *    Handles alignment by aligning 2 byte attributes on short boundries
  921.  *    and 3 or 4 byte attributes on long word boundries on a vax; and
  922.  *    aligning non-byte attributes on short boundries on a sun.  Does
  923.  *    not properly align fixed length arrays of 1 or 2 byte types (yet).
  924.  *
  925.  *    Null attributes are indicated by a 'n' in the appropriate byte
  926.  *    of the null[].  Non-null attributes are indicated by a ' ' (space).
  927.  *
  928.  *    Fix me.  (Figure that must keep context if debug--allow give oid.)
  929.  *    Assumes in order.
  930.  * ----------------
  931.  */
  932.  
  933. HeapTuple
  934. heap_formtuple(numberOfAttributes, tupleDescriptor, value, nulls)
  935.     AttributeNumber    numberOfAttributes;
  936.     TupleDescriptor    tupleDescriptor;
  937.     Datum        value[];
  938.     char        nulls[];
  939. {
  940.     char    *tp;    /* tuple pointer */
  941.     HeapTuple    tuple;    /* return tuple */
  942.     int        bitmaplen;
  943.     long    len;
  944.     int        hoff;
  945.     bool    hasnull = false;
  946.     int        i;
  947.     
  948.     len = sizeof *tuple - sizeof tuple->t_bits;
  949.  
  950.     for (i = 0; i < numberOfAttributes && !hasnull; i++)
  951.     {
  952.     if (nulls[i] != ' ') hasnull = true;
  953.     }
  954.  
  955.     if (numberOfAttributes > MaxHeapAttributeNumber)
  956.     elog(WARN, "heap_formtuple: numberOfAttributes of %d > %d",
  957.          numberOfAttributes, MaxHeapAttributeNumber);
  958.  
  959.     if (hasnull)
  960.     {
  961.         bitmaplen = BITMAPLEN(numberOfAttributes);
  962.         len       += bitmaplen;
  963.     }
  964.     hoff = len;
  965.  
  966.     len += ComputeDataSize(numberOfAttributes, tupleDescriptor, value, nulls);
  967.     
  968.     tp =     (char *) palloc(len);
  969.     tuple =     LintCast(HeapTuple, tp);
  970.     
  971.     bzero(tp, (int)len);
  972.     
  973.     tuple->t_len =     len;
  974.     tuple->t_natts =     numberOfAttributes;
  975.     tuple->t_hoff = hoff;
  976.     tuple->t_tmin = INVALID_ABSTIME;
  977.     tuple->t_tmax = INVALID_ABSTIME;
  978.     
  979.     DataFill((Pointer) tuple + tuple->t_hoff,
  980.          numberOfAttributes,
  981.          tupleDescriptor,
  982.          value,
  983.          nulls,
  984.              &tuple->t_infomask,
  985.          (hasnull ? tuple->t_bits : NULL));
  986.     
  987.     /*
  988.      * initialize rule lock information to an EMPTY lock
  989.      * (not to be confused with an InvalidRuleLock).
  990.      */
  991.     tuple->t_locktype = MEM_RULE_LOCK;
  992.     tuple->t_lock.l_lock = prs2MakeLocks();
  993.     
  994.     return (tuple);
  995. }
  996.  
  997. /* ----------------
  998.  *    heap_modifytuple
  999.  *
  1000.  *    forms a new tuple from an old tuple and a set of replacement values.
  1001.  * ----------------
  1002.  */
  1003.  
  1004. HeapTuple
  1005. heap_modifytuple(tuple, buffer, relation, replValue, replNull, repl)
  1006.     HeapTuple    tuple;
  1007.     Buffer    buffer;
  1008.     Relation    relation;
  1009.     Datum    replValue[];
  1010.     char    replNull[];
  1011.     char    repl[];
  1012. {
  1013.     AttributeOffset    attoff;
  1014.     AttributeNumber    numberOfAttributes;
  1015.     Datum        *value;
  1016.     char        *nulls;
  1017.     bool        isNull;
  1018.     HeapTuple        newTuple;
  1019.     int            madecopy;
  1020.     
  1021.     /* ----------------
  1022.      *    sanity checks
  1023.      * ----------------
  1024.      */
  1025.     Assert(HeapTupleIsValid(tuple));
  1026.     Assert(BufferIsValid(buffer) || RelationIsValid(relation));
  1027.     Assert(HeapTupleIsValid(tuple));
  1028.     Assert(PointerIsValid(replValue));
  1029.     Assert(PointerIsValid(replNull));
  1030.     Assert(PointerIsValid(repl));
  1031.     
  1032.     /* ----------------
  1033.      *    if we're pointing to a disk page, then first
  1034.      *  make a copy of our tuple so that all the attributes
  1035.      *  are available.  XXX this is inefficient -cim
  1036.      * ----------------
  1037.      */
  1038.     madecopy = 0;
  1039.     if (BufferIsValid(buffer) == true) {
  1040.     relation =     (Relation) BufferGetRelation(buffer);
  1041.     tuple =     heap_copytuple(tuple, buffer, relation);
  1042.     madecopy = 1;
  1043.     }
  1044.     
  1045.     numberOfAttributes = RelationGetRelationTupleForm(relation)->relnatts;
  1046.  
  1047.     /* ----------------
  1048.      *    allocate and fill value[] and nulls[] arrays from either
  1049.      *  the tuple or the repl information, as appropriate.
  1050.      * ----------------
  1051.      */
  1052.     value = (Datum *)    palloc(numberOfAttributes * sizeof *value);
  1053.     nulls =  (char *)    palloc(numberOfAttributes * sizeof *nulls);
  1054.     
  1055.     for (attoff = 0;
  1056.      attoff < numberOfAttributes;
  1057.      attoff += 1) {
  1058.     
  1059.     if (repl[ attoff ] == ' ') {
  1060.         value[ attoff ] =
  1061.         PointerGetDatum( heap_getattr(tuple,
  1062.                           InvalidBuffer, 
  1063.                 AttributeOffsetGetAttributeNumber(attoff),
  1064.                 RelationGetTupleDescriptor(relation),
  1065.                           &isNull) );
  1066.         
  1067.         nulls[ attoff ] = (isNull) ? 'n' : ' ';
  1068.         
  1069.     } else if (repl[ attoff ] != 'r') {
  1070.         elog(WARN, "heap_modifytuple: repl is \\%3d", repl[ attoff ]);
  1071.         
  1072.     } else { /* == 'r' */
  1073.         value[ attoff ] = replValue[ attoff ];
  1074.         nulls[ attoff ] =  replNull[ attoff ];
  1075.     }
  1076.     }
  1077.  
  1078.     /* ----------------
  1079.      *    create a new tuple from the values[] and nulls[] arrays
  1080.      * ----------------
  1081.      */
  1082.     newTuple = heap_formtuple(numberOfAttributes,
  1083.                  RelationGetTupleDescriptor(relation),
  1084.                  value,
  1085.                  nulls);
  1086.     
  1087.     /* ----------------
  1088.      *    copy the header except for the initial t_len and final t_bits
  1089.      * ----------------
  1090.      */
  1091.     bcopy((char *) &tuple->t_ctid,
  1092.       (char *) &newTuple->t_ctid,    /*XXX*/
  1093.       ((char *) &tuple->t_hoff - (char *) &tuple->t_ctid)); /*XXX*/
  1094.     
  1095.     newTuple->t_natts = numberOfAttributes;    /* fix t_natts just in case */
  1096.  
  1097.     /* ----------------
  1098.      *    if we made a copy of the tuple, then free it.
  1099.      * ----------------
  1100.      */
  1101.     if (madecopy)
  1102.     pfree((char *) tuple);
  1103.     
  1104.     return
  1105.     newTuple;
  1106. }
  1107.  
  1108. /* ----------------------------------------------------------------
  1109.  *            other misc functions
  1110.  * ----------------------------------------------------------------
  1111.  */
  1112. /* ----------------
  1113.  *    getstruct    - return s pointer to the structure in the tuple
  1114.  *
  1115.  *    To be called with a tuple from a system relation only, since this
  1116.  *    assumes that only system tuples are guarenteed to reside on a single
  1117.  *    page.  C code can call the macro GETSTRUCT() in <htup.h>.  This
  1118.  *    should probably not be called by user code.
  1119.  *
  1120.  *    Note:
  1121.  *        Does not return a palloc'd version of the structure.
  1122.  *
  1123.  *    Should a similar call also be made for index tuples?
  1124.  * ----------------
  1125.  */
  1126.  
  1127. char *
  1128. getstruct(tup)
  1129.     HeapTuple tup;
  1130. {
  1131.     return (GETSTRUCT(tup));
  1132. }
  1133.  
  1134. /* ----------------
  1135.  *    slowgetattr
  1136.  *
  1137.  *      XXX - Currently NOT USED, but probably should not go away.
  1138.  * ----------------
  1139.  */
  1140.  
  1141. char    *
  1142. slowgetattr(tup, b, attnum, att, isnull)
  1143.     HeapTuple    tup;
  1144.     Buffer    b;
  1145.     unsigned    attnum;
  1146.     struct    attribute *att[];
  1147.     bool    *isnull;
  1148. {
  1149.     register int            bitmask;
  1150.     register struct    attribute    **ap;    /* attribute pointer */
  1151.     register char            *bp;    /* tup->t_bits pointer */
  1152.     register char            *tp;    /* tuple pointer */
  1153.     ItemSubposition            opos;
  1154.     unsigned long            skip, size[2];
  1155.     int                    byte;
  1156.     int                    finalbit;
  1157.     int                    bitrange;
  1158.     
  1159.     ItemSubposition    startpskip();
  1160.     int            pskip(), pfill();
  1161.     extern        endpskip();
  1162.     
  1163.     Assert(PointerIsValid(isnull));
  1164.     Assert(attnum > 0);
  1165.     
  1166.     size[0] = 4l;            /* palloc format */
  1167.     byte = --attnum >> 3;
  1168.     finalbit = 1 << (attnum & 07);
  1169.     bp = tup->t_bits;
  1170.     if (! (bp[byte] & finalbit)) {
  1171.     *isnull = true;
  1172.     return (NULL);
  1173.     }
  1174.     
  1175.     *isnull = false;
  1176.     ap = att;
  1177.     opos = startpskip(b, (struct reldesc *)NULL, &tup->t_ctid);
  1178.     bitrange = CSIGNBIT;
  1179.     skip = 0l;
  1180.     while (byte >= 0) {
  1181.     if (!byte--)
  1182.         bitrange = finalbit >> 1;
  1183.     for (bitmask = 1; bitmask <= bitrange; bitmask <<= 1) {
  1184.         if (*bp & bitmask)
  1185.         if ((*ap)->attlen < 0) {
  1186.             skip = LONGALIGN(skip);
  1187.             if (pskip(opos, skip) < 0)
  1188.             elog(WARN, "slowgetattr: pskip");
  1189.             if (PNOBREAK(opos, sizeof (long))) {
  1190.             PSKIP(opos, sizeof (long));
  1191.             skip = PSIZE(opos->op_cp);
  1192.             } else {
  1193.             if (pfill(opos, (char *)
  1194.                   (size + 1)) < 0)
  1195.                 elog(WARN, "slowgetattr");
  1196.             skip = size[1];
  1197.             }
  1198.         } else if ((*ap)->attlen >= 3)
  1199.             skip = LONGALIGN(skip) + (*ap)->attlen;
  1200.         else if ((*ap)->attlen == 2)
  1201.             skip = 2 + SHORTALIGN(skip);
  1202.         else if (!(*ap)->attlen)
  1203.             elog(WARN, "slowgetattr: 0 attlen");
  1204.         else
  1205.             skip++;
  1206.         ap++;
  1207.     }
  1208.     bp++;
  1209.     }
  1210.     if ((*ap)->attlen < 0)
  1211.     skip = LONGALIGN(skip);
  1212.     else if (!(*ap)->attbyval) {
  1213.     if ((*ap)->attlen >= 3)
  1214.         skip = LONGALIGN(skip);
  1215.     else if ((*ap)->attlen == 2)
  1216.         skip = SHORTALIGN(skip);
  1217.     } else
  1218.     switch ((int)(*ap)->attlen) {
  1219.     case 2:
  1220.         skip = SHORTALIGN(skip);
  1221.         break;
  1222.     case 3:
  1223.     case 4:
  1224.         skip = LONGALIGN(skip);
  1225.     default:
  1226.         ;
  1227.     }
  1228.     if (pskip(opos, skip) < 0)
  1229.     elog(WARN, "slowgetattr: pskip failed");
  1230.     if ((*ap)->attlen < 0) {
  1231.     if (PNOBREAK(opos, sizeof (long))) {
  1232.         PSKIP(opos, sizeof (long));
  1233.         size[1] = PSIZE(opos->op_cp);
  1234.     } else if (pfill(opos, (char *)(size + 1)) < 0)
  1235.         elog(WARN, "slowgetattr: failed pfill");
  1236.     if (b == opos->op_db && PNOBREAK(opos, (unsigned)size[1]))
  1237.         tp = opos->op_cp;
  1238.     else {
  1239.         tp = (char *) palloc(size[1]);
  1240.         if (pfill(opos, tp) < 0)
  1241.         elog(WARN, "slowgetattr: failed pfill$");
  1242.     }
  1243.     } else if (!(*ap)->attbyval) {
  1244.     if (b == opos->op_db && PNOBREAK(opos, (unsigned)(*ap)->attlen))
  1245.         tp = opos->op_cp;
  1246.     else {
  1247.         tp = (char *) palloc((*ap)->attlen);
  1248.         if (pfill(opos, tp) < 0)
  1249.         elog(WARN, "slowgetattr: failed pfill$2");
  1250.     }
  1251.     } else
  1252.     switch ((int)(*ap)->attlen) {
  1253.     case 1:
  1254.         if (!opos->op_len) {
  1255.         size[0] = 1l;
  1256.         if (pfill(opos, (char *)(size + 1)) < 0)
  1257.             elog(WARN, "slowgetattr: failed pfill$3");
  1258.         tp = (char *)*(char *)(size + 1);
  1259.         } else
  1260.         tp = (char *)*opos->op_cp;
  1261.         break;
  1262.     case 2:
  1263.         if (opos->op_len < 2) {
  1264.         size[0] = 2l;
  1265.         if (pfill(opos, (char *)(size + 1)) < 0)
  1266.             elog(WARN, "slowgetattr: failed pfill$4");
  1267.         tp = (char *)*(short *)(size + 1);
  1268.         } else
  1269.         tp = (char *)*(short *)opos->op_cp;
  1270.         break;
  1271.     case 3:                    /* XXX */
  1272.         elog(WARN, "slowgetattr: no len 3 attbyval yet");
  1273.     case 4:
  1274.         if (opos->op_len < 2) {
  1275.         if (pfill(opos, (char *)(size + 1)) < 0)
  1276.             elog(WARN, "slowgetattr: failed pfill$5");
  1277.         tp = (char *)size[1];
  1278.         } else
  1279.         tp = (char *)*(long *)opos->op_cp;
  1280.         break;
  1281.     default:
  1282.         elog(WARN, "slowgetattr: len %d attbyval", (*ap)->attlen);
  1283.     }
  1284.     endpskip(opos);
  1285.     return (tp);
  1286. }
  1287.  
  1288. HeapTuple
  1289. heap_addheader(natts, structlen, structure)
  1290.     uint32    natts;            /* max domain index */
  1291.     int        structlen;        /* its length */
  1292.     char    *structure;        /* pointer to the struct */
  1293. {
  1294.     register char    *tp;    /* tuple data pointer */
  1295.     HeapTuple        tup;
  1296.     int            bitmasklen;
  1297.     int            bitmask;
  1298.     long        len;
  1299.     int            i;
  1300.     int            hoff;
  1301.     extern        bzero();
  1302.     extern        bcopy();
  1303.     
  1304.     AssertArg(natts > 0);
  1305.  
  1306.     len = sizeof (HeapTupleData) - sizeof (tup->t_bits);
  1307.  
  1308.     hoff = len;
  1309.     len += structlen;
  1310.     tp = (char *) palloc(len);
  1311.     tup = (HeapTuple) tp;
  1312.     bzero(tup, len);
  1313.  
  1314.     tup->t_len = (short) len;            /* XXX */
  1315.     tp += tup->t_hoff = hoff;
  1316.     tup->t_natts = natts;
  1317.     tup->t_infomask = 0;
  1318.  
  1319.     bcopy(structure, tp, structlen);
  1320.  
  1321.     /*
  1322.      * initialize rule lock
  1323.      */
  1324.     tup->t_locktype = MEM_RULE_LOCK;
  1325.     tup->t_lock.l_lock = NULL;
  1326.     
  1327.     return (tup);
  1328. }
  1329.  
  1330. /* 
  1331.    for debugging purpose only.  will only be called in dbx
  1332. */
  1333. int
  1334. heapTupleHeaderSize()
  1335. {
  1336.     return(sizeof(HeapTupleData));
  1337. }
  1338.